﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using AviationSimulator.DataItems;
using AviationSimulator.Properties;

namespace AviationSimulator.GUI
{
    public partial class EditMathFunction : Form
    {
        private readonly List<ParameterFunction> _parameterFunctions;
        private readonly string _parameterName;

        private readonly ParameterFunction _currentFunction;

        public EditMathFunction(List<ParameterFunction> parameterFunctions, string parameterName)
        {
            InitializeComponent();

            _parameterFunctions = parameterFunctions;
            _parameterName = parameterName;
            
            try
            {
                _currentFunction =
                    _parameterFunctions.First(parameterFunction => parameterFunction.ParameterName == _parameterName);

                if (_currentFunction.MathFunction != null)
                {
                    SelectFunctionComboBox.SelectedItem = GetMathFunctionName(_currentFunction.MathFunction.Name);
                    DiscrecityTextBox.Text = _currentFunction.MathFunction.Discrecity.ToString();
                    LowerRangeTextBox.Text = _currentFunction.MathFunction.LowRange.ToString();
                    UpperRangeTextBox.Text = _currentFunction.MathFunction.UpperRange.ToString();

                    AParameterTextBox.Text = _currentFunction.MathFunction.A.ToString();
                    BParameterTextBox.Text = _currentFunction.MathFunction.B.ToString();
                    CParameterTextBox.Text = _currentFunction.MathFunction.C.ToString();
                }
                else
                {
                    _currentFunction.MathFunction = new MathFunction();
                }
            }
            catch (InvalidOperationException)
            {
                _currentFunction = null;
            }
        }

        private void CancelButton_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
            Close();
        }

        private void OkButtonClick(object sender, EventArgs e)
        {
            string selectedFunction;

            try
            {
                selectedFunction = SelectFunctionComboBox.SelectedItem.ToString();
            }
            catch (NullReferenceException)
            {
                MessageBox.Show(Resources.ChooseFunctionMessage);
                return;
            }
            

            if (!string.IsNullOrEmpty(selectedFunction))
            {
                MathFunctionName mathFunctionName = GetMathFunctionName(selectedFunction);

                try
                {
                    var mathFunction = new MathFunction();
                    mathFunction.Name = mathFunctionName;
                    mathFunction.Discrecity = Convert.ToDouble(DiscrecityTextBox.Text);
                    mathFunction.LowRange = Convert.ToDouble(LowerRangeTextBox.Text);
                    mathFunction.UpperRange = Convert.ToDouble(UpperRangeTextBox.Text);
                    mathFunction.A = string.IsNullOrEmpty(AParameterTextBox.Text)
                                         ? 0
                                         : Convert.ToInt32(AParameterTextBox.Text);
                    mathFunction.B = string.IsNullOrEmpty(BParameterTextBox.Text)
                                         ? 0
                                         : Convert.ToInt32(BParameterTextBox.Text);

                    mathFunction.C = string.IsNullOrEmpty(CParameterTextBox.Text) 
                                         ? 0 :
                                         Convert.ToInt32(CParameterTextBox.Text);

                    ChackMathFunctionParameters(mathFunction);

                    if (_currentFunction == null)
                    {
                        _parameterFunctions.Add(new ParameterFunction
                        {
                            ParameterName = _parameterName,
                            MathFunction = mathFunction
                        });
                    }
                    else
                    {
                        _currentFunction.MathFunction = mathFunction;
                    }

                    DialogResult = DialogResult.OK;
                    Close();
                }
                catch (FormatException ex)
                {
                    MessageBox.Show(Resources.MathFunctionInvalidParameters + ": " + ex.Message);
                }
            }
        }

        private void ChackMathFunctionParameters(MathFunction mathFunction)
        {
            switch (mathFunction.Name)
            {
                case MathFunctionName.Ln:
                    if (mathFunction.LowRange <= 0)
                        throw new FormatException("Low range is lower or equal to 0");

                    if (mathFunction.UpperRange <= 0)
                        throw new FormatException("Upper range is lower or equal to 0");

                    break;
            }

            if (mathFunction.Discrecity < 0)
                throw new FormatException("Discrecity is lower that 0");
        }

        private static MathFunctionName GetMathFunctionName(string selectedFunction)
        {
            if (selectedFunction.Equals("Linear"))
                return MathFunctionName.Linear;

            if (selectedFunction.Equals("Quadratic"))
                return MathFunctionName.Exponential;

            if (selectedFunction.Equals("Exponential"))
                return MathFunctionName.Exponential;

            if (selectedFunction.Equals("Natural logarithm"))
                return MathFunctionName.Ln;

            if (selectedFunction.Equals("Sin"))
                return MathFunctionName.Sin;

            return MathFunctionName.Linear;
        }

        private static string GetMathFunctionName(MathFunctionName functionName)
        {
            switch (functionName)
            {
                case MathFunctionName.Linear:
                    return "Linear";

                case MathFunctionName.Quedratic:
                    return "Quadratic";

                case MathFunctionName.Exponential:
                    return "Exponential";

                case MathFunctionName.Ln:
                    return "Natural logarithm";

                case MathFunctionName.Sin:
                    return "Sin";
            }

            return string.Empty;
        }

        private void SelectFunctionComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            SetControlsProperties(SelectFunctionComboBox.SelectedItem.ToString());

            DiscrecityTextBox.Text = string.Empty;
            LowerRangeTextBox.Text = string.Empty;
            UpperRangeTextBox.Text = string.Empty;


            AParameterTextBox.Text = string.Empty;
            BParameterTextBox.Text = string.Empty;
            CParameterTextBox.Text = string.Empty;
        }

        private void SetControlsProperties(string  mathFunctionName)
        {
            if (mathFunctionName.Equals("Linear"))
            {
                AParameterlabel.Visible = true;
                AParameterTextBox.Visible = true;

                BParameterLabel.Visible = true;
                BParameterTextBox.Visible = true;

                CParameterLabel.Visible = false;
                CParameterTextBox.Visible = false;

                Size = new Size(352, 194);
                OKButton.Location = new Point(154, 117);
                CancelButton.Location = new Point(242, 117);

                return;
            }

            if (mathFunctionName.Equals("Quadratic"))
            {
                AParameterlabel.Visible = true;
                AParameterTextBox.Visible = true;

                BParameterLabel.Visible = true;
                BParameterTextBox.Visible = true;

                CParameterLabel.Visible = true;
                CParameterTextBox.Visible = true;

                Size = new Size(352, 194);
                OKButton.Location = new Point(154, 117);
                CancelButton.Location = new Point(242, 117);
            }
            else
            {
                AParameterlabel.Visible = false;
                AParameterTextBox.Visible = false;

                BParameterLabel.Visible = false;
                BParameterTextBox.Visible = false;

                CParameterLabel.Visible = false;
                CParameterTextBox.Visible = false;

                Size = new Size(352, 163);
                OKButton.Location = new Point(154, 88);
                CancelButton.Location = new Point(242, 88);
            }
        }
    }
}
